// ===========================================================
// FileName : Mem1kx32Bidir.v
// Function : Bidirectional enhancement of a 1k static RAM with 
//            storage arranged as words of 32 bits.
//
// ------------------------------------------------------------
//
// Author   : QilinZhao
// Version  : v-1.0
// Date     : 2013-09-10
// E-mail   : forqilin@163.com
// Copyright: QiXin Studio
// ============================================================

`timescale 1ns/100ps

`include "Mem1kx32.v"  // copy the code in here

module Mem1kx32Bidir
        #(parameter AdrHi = 4) // Default length of RAM storage.
        ( output Dready        // Data valid during a read.
         , ParityErr           // Parity error on read.
         , inout[31:0] DataIO  // For read from storage.
         , input[AdrHi:0] Addr // Address bus.
         , input ClockIn       // Clocks data in or out.
         , ChipEna             // Enables data output drivers.
         , Read       // Stored data are copied to Data[].
         , Write      // Data[] values replace stored values.
         );
  
  // The wrapper bidirectional control:
  localparam MemWid = (1<<AdrHi+1);
  
  wire [MemWid-1:0] ReadData;
  assign DataIO = (Read==1'b1)? ReadData : 'bz;
  // assign DataI=DataIO; // tri-state PAD: I2C, SD, MMC
  
  // The instantiated old RAM:
  Mem1kx32 #(.AdrHi(AdrHi)) // Pass wrapper default down. 
  u_Mem1kx32    ( .Dready   (Dready) 
                , .ParityErr(ParityErr)
                , .DataO    (ReadData)
				        , .DataI    (DataIO)
				        , .Addr     (Addr)
                , .ClockIn  (ClockIn)
				        , .ChipEna  (ChipEna)
                , .Read     (Read)
				        , .Write    (Write)
                ); 

endmodule // Mem1kx32Bidir.


// ------------------------------------------------------------
// Testbench for the bidirectional RAM:
//
`ifdef DC
`else
module Mem1kTest; // no I/O for testbench

parameter AdrHiParam = 4;

wire DreadyWatch, ParityErrWatch;
wire[31:0] DataStim;        // Data stimulus must be net.
 reg[31:0] DataReg;         // To drive the data stim net.
reg [AdrHiParam:0] AddrStim;
reg ClockInStim
  , ChipEnaStim
  , ReadStim
  , WriteStim;

// New, bidirectional design instance:
Mem1kx32Bidir // No parameter passed, so default used.
u_Mem1kx32Bidir (  .Dready     (DreadyWatch)
                  ,.ParityErr  (ParityErrWatch)
                  , .DataIO    (DataStim)
				          , .Addr      (AddrStim)
                  , .ClockIn   (ClockInStim)
				          , .ChipEna   (ChipEnaStim)
                  , .Read      (ReadStim)
				          , .Write     (WriteStim)
                );

assign DataStim = DataReg;

always@(ClockInStim) #10 ClockInStim <= ~ClockInStim;

initial
  begin // Blocking assignments used for testbench:
       DataReg     =  'b0;
       ChipEnaStim = 1'b0;
       ReadStim    = 1'b0;
       WriteStim   = 1'b0;
       AddrStim    = 5'b00000;
       ClockInStim = 1'b0;
  #1   ChipEnaStim = 1'b1;
  #4   DataReg     = 32'h1111_ffff;
  #1   WriteStim   = 1'b1;
  #30  WriteStim   = 1'b0;
  #1   DataReg     = 'bz;
  #1   ReadStim    = 1'b1;
  #39  ReadStim    = 1'b0;
  #15  ChipEnaStim = 1'b0;
  #55  ChipEnaStim = 1'b1;
  
  #0   DataReg     = 'bz;
  #1   ReadStim    = 1'b1;
  #39  ReadStim    = 1'b0;
  #0   AddrStim    = 5'b00001;
  #10  DataReg     = 32'h11ff_eeee;
  #1   WriteStim   = 1'b1;
  #50  WriteStim   = 1'b0;
  #1   DataReg     = 'bz;
  #5   ReadStim    = 1'b1;
  #39  ReadStim    = 1'b0;
  #5   AddrStim    = 5'b00000;
  #5   ReadStim    = 1'b1;

  #80 $finish;
  end
  
  initial begin
    $vcdpluson();
  end
endmodule  // Mem1kTest
`endif

